package com.chuangke.mds.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.jsoup.Jsoup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.CriteriaQueryBuilder;
import org.springframework.data.elasticsearch.core.query.HighlightQuery;
import org.springframework.data.elasticsearch.core.query.highlight.Highlight;
import org.springframework.data.elasticsearch.core.query.highlight.HighlightField;
import org.springframework.data.elasticsearch.core.query.highlight.HighlightFieldParameters;
import org.springframework.stereotype.Service;

import com.chuangke.elasticsearch.model.ElasticQuery;
import com.chuangke.mds.entity.Knowledge;
import com.chuangke.mds.service.KnowledgeSearchService;

import cn.hutool.core.util.StrUtil;

@Service
public class KnowledgeSearchServiceImpl implements KnowledgeSearchService {

	@Autowired
	private ElasticsearchOperations operations;

	@Override
	public Page<Knowledge> search(ElasticQuery<Knowledge> elasticQuery) {
		int pageNum = (int) elasticQuery.getPageNum() ;
		pageNum = pageNum==0? 0 : pageNum-1 ;
		elasticQuery.setPageNum(pageNum);
		return doSearch(elasticQuery);
	}

	private Page<Knowledge> doSearch(ElasticQuery<Knowledge> elasticQuery) {
		Map<String, Object> params = elasticQuery.getQuery();
		// 构建查询
		CriteriaQueryBuilder builder = new CriteriaQueryBuilder(buildCriteria(params))
				.withHighlightQuery(getHighlightQuery())
//                .withSort(Sort.by(Sort.Direction.DESC, "createdAt"))
                .withPageable(PageRequest.of((int) elasticQuery.getPageNum(), (int) elasticQuery.getPageSize()));// 页码从0开始

		CriteriaQuery query = new CriteriaQuery(builder);

		// 通过elasticsearchTemplate查询
		SearchHits<Knowledge> result = operations.search(query, Knowledge.class);
		// 处理结果
		List<SearchHit<Knowledge>> searchHitList = result.getSearchHits();
		List<Knowledge> discussPostList = new ArrayList<>();
		for (SearchHit<Knowledge> hit : searchHitList) {
			Knowledge post = hit.getContent();
			// 将高亮结果添加到返回的结果类中显示
			List<String> nameHighlight = hit.getHighlightField("name");
			if (!nameHighlight.isEmpty()) {
				post.setName(nameHighlight.get(0));
			}
			List<String> contentHighlight = hit.getHighlightField("bodyContent");
			if (!contentHighlight.isEmpty()) {
				post.setBodyContent(contentHighlight.get(0));
			} else {
				if (!StrUtil.isBlank(post.getContent())) {
					String content = Jsoup.parse(post.getBodyContent()).text();
					content = content.substring(0, Math.min(content.length(), 150));
					post.setBodyContent(content + ".......");
				}
			}
			discussPostList.add(post);

		}
		// 构建Page对象
		return new PageImpl<>(discussPostList,
				PageRequest.of((int) elasticQuery.getPageNum(), (int) elasticQuery.getPageSize()),
				result.getTotalHits());
	}

	@SuppressWarnings("unchecked")
	private Criteria buildCriteria(Map<String, Object> params) {
		Criteria criteria = new Criteria();
		if (params == null) {
			return criteria;
		}
		// 搜索关键字
		String wd = (String) params.get("wd");
		List<String> issueDate = (List<String>) params.get("issueDate");
		List<String> effectiveDate = (List<String>) params.get("effectiveDate");
		String bisTypeId = (String) params.get("bisTypeId");
		String levelId = (String) params.get("levelId");

		if (!StrUtil.isBlank(wd)) {
            criteria.and(new Criteria("bodyContent").matches(wd).or(new Criteria("name").matches(wd)));
			criteria.and(new Criteria("name").matches(wd).or(new Criteria("bodyContent").matches(wd)));
		}
		if (!CollectionUtils.isEmpty(effectiveDate)) {
			criteria.and(new Criteria("effectiveDate").between(effectiveDate.get(0), effectiveDate.get(1)));
		}
		if (!CollectionUtils.isEmpty(issueDate)) {
			criteria.and(new Criteria("issueDate").between(issueDate.get(0), issueDate.get(1)));
		}
		if (!StrUtil.isBlank(bisTypeId) && !"all".equals(bisTypeId)) {
			criteria.and(new Criteria("bisTypeId").matchesAll(bisTypeId));
		}
		if (!StrUtil.isBlank(levelId) && !"all".equals(levelId)) {
			criteria.and(new Criteria("levelId").matchesAll(levelId));
		}
		return criteria;
	}

	/**
	 * 高亮查询
	 *
	 * @return
	 */
	private HighlightQuery getHighlightQuery() {
		List<HighlightField> highlightFieldList = new ArrayList<>();

		String[] pretags = { "<font color='red'>" };
		String[] postTags = { "</font>" };

		HighlightField highlightField = new HighlightField("name",
				HighlightFieldParameters.builder().withPreTags(pretags).withPostTags(postTags).build());
		highlightFieldList.add(highlightField);

		highlightField = new HighlightField("bodyContent",
				HighlightFieldParameters.builder().withPreTags(pretags).withPostTags(postTags).build());
		highlightFieldList.add(highlightField);

		Highlight highlight = new Highlight(highlightFieldList);
		return new HighlightQuery(highlight, Knowledge.class);
	}
}
